package indi.zhifa.engine.core.common.utils;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.util.Date;

import static java.time.temporal.ChronoField.*;
import static java.time.temporal.ChronoField.NANO_OF_SECOND;

@Slf4j
public class TimeUtil {

    static DateTimeFormatter localDateTimeDf;
    static DateTimeFormatter localDateDf;
    static DateTimeFormatter localTimeDf;

    static{

        localTimeDf = new DateTimeFormatterBuilder()
                .appendValue(HOUR_OF_DAY, 2)
                .appendLiteral(':')
                .appendValue(MINUTE_OF_HOUR, 2)
                .optionalStart()
                .appendLiteral(':')
                .appendValue(SECOND_OF_MINUTE, 2)
                .toFormatter();
        localDateDf = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .toFormatter();

        localDateTimeDf = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral('T')
                .append(localTimeDf)
                .toFormatter();

    }



    public static Date localDateTimeToDate(final LocalDateTime localDateTime) {
        if (null == localDateTime) {
            return null;
        }
        final ZoneId zoneId = ZoneId.systemDefault();
        final ZonedDateTime zdt = localDateTime.atZone(zoneId);
        final Date date = Date.from(zdt.toInstant());
        return date;
    }

    public static LocalDateTime dateToLocalDateTime(final Date date) {
        if (null == date) {
            return null;
        }
        final Instant instant = date.toInstant();
        final ZoneId zoneId = ZoneId.systemDefault();
        final LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime;
    }

    /**
     * 把localDateTime转成0时区2000年1月1日0点0分0秒的秒数
     * @param localDateTime 时间
     * @return
     */
    static public Long LocalDateTimeToSecond(LocalDateTime localDateTime){
        /*
        中国时间：
        ZoneId.of("Asia/Shanghai")*/
        // 本项目使用0时区
        long seconds = localDateTime.toEpochSecond(ZoneOffset.UTC);
        LocalDateTime referenceTime = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
        long seconds2000 = referenceTime.toEpochSecond(ZoneOffset.UTC);
        long diffSeconds = seconds - seconds2000;
        return diffSeconds;
    }

    /**
     * 把LocalDateTimeToSecond函数转成的秒数，转回LocalDateTime，使用服务器时区
     *
     * @param pSecond LocalDateTimeToSecond函数转成的秒数
     * @return
     */
    static public LocalDateTime parseFromSecond(Long pSecond){
        LocalDateTime referenceTime = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
        long seconds2000 = referenceTime.toEpochSecond(ZoneOffset.UTC);
        long seconds = seconds2000 + pSecond;
        LocalDateTime utcDateTime = LocalDateTime.ofEpochSecond(seconds, 0, ZoneOffset.UTC);
        ZonedDateTime utcZonedDateTime = utcDateTime.atZone(ZoneOffset.UTC);
        ZoneId serverZone  = ZoneId.systemDefault();
        ZonedDateTime serverZonedDateTime = utcZonedDateTime.withZoneSameInstant(serverZone);
        LocalDateTime serverLocalDateTime = serverZonedDateTime.toLocalDateTime();
        return serverLocalDateTime;
    }

    /**
     * 把一般时间转成0时区时间
     * @param localDateTime
     * @return
     */
    static public LocalDateTime zeroLocalDateTime(LocalDateTime localDateTime){
        ZoneId serverZone = ZoneId.systemDefault();
        ZonedDateTime serverZonedDateTime = localDateTime.atZone(serverZone);
        ZonedDateTime utcZonedDateTime = serverZonedDateTime.withZoneSameInstant(ZoneOffset.UTC);
        LocalDateTime utcLocalDateTime = utcZonedDateTime.toLocalDateTime();
        return utcLocalDateTime;
    }

    static public LocalDateTime now(){
        return zeroLocalDateTime(LocalDateTime.now());
    }

    static public Long nowSecond(){
        LocalDateTime nowTime = now();
        return LocalDateTimeToSecond(nowTime);
    }

    static public LocalDateTime convertToLocalDateTime(String source) {
        if(StrUtil.isEmptyIfStr(source)){
            return null;
        }
        LocalDateTime time = null;
        try{
            time = LocalDateTime.parse(source, localDateTimeDf);
        }catch(Exception e){
            log.info(source + " 无法转换为LocalDateTime");
        }
        return time;
    }

    static public LocalDate convertToLocalDate(String source) {
        if(!StrUtil.isEmptyIfStr(source)){
            return null;
        }
        LocalDate time = null;
        try{
            time = LocalDate.parse(source, localDateDf);
        }catch(Exception e){
            log.info(source + " 无法转换为LocalDate");
        }
        return time;
    }

    static public LocalTime convertToLocalTime(String source) {
        if(!StrUtil.isEmptyIfStr(source)){
            return null;
        }
        LocalTime time = null;
        try {
            time = LocalTime.parse(source, localTimeDf);
        } catch (Exception e) {
            log.info(source + " 无法转换为LocalTime");
        }
        return time;
    }

    static public String nowStr(){
        return LocalDateTimeUtil.format(now(), localDateTimeDf);
    }



}
